package com.design.reactor.stretchIO._4_masterSlaveReactorMultiThread;

import com.design.reactor.stretchIO._4_masterSlaveReactorMultiThread.handler.AcceptorHandler;
import com.design.reactor.stretchIO._4_masterSlaveReactorMultiThread.handler.Handler;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.Set;

public class MainReactor implements Runnable {
    private final Selector selector; // mainReactor用的selector

    public MainReactor(int port) throws IOException {
        selector = Selector.open();
        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.socket().bind(new InetSocketAddress(port)); // 在ServerSocketChannel綁定監聽端口
        ssc.configureBlocking(false); // 設置ServerSocketChannel為非阻塞
        SelectionKey sk = ssc.register(selector, SelectionKey.OP_ACCEPT); // ServerSocketChannel向selector註冊一個OP_ACCEPT事件，然後返回該通道的key
        sk.attach(new AcceptorHandler(ssc)); // 給定key一個附加的Acceptor對象
    }

    //就是一个死循环
    @Override
    public void run() {
        while (!Thread.interrupted()) { // 在線程被中斷前持續運行
            try {
                //没有事件就緒时，继续下一次循环。
                selector.select();
                Set<SelectionKey> selectedKeys = selector.selectedKeys(); // 取得所有已就緒事件的key集合
                for (SelectionKey selectedKey : selectedKeys) {
                    if (selectedKey.isReadable()) {
                        System.out.println("线程 ：" + Thread.currentThread().getName() + ",当前类 ；" + getClass().getName() + " 的 hashCode :" + this.hashCode() + ",此 selector< " + selector.hashCode() + " > 多路复用器上发生的事件是 ：可读事件");
                    } else if (selectedKey.isWritable()) {
                        System.out.println("线程 ：" + Thread.currentThread().getName() + ",当前类 ；" + getClass().getName() + " 的 hashCode :" + this.hashCode() + ",此 selector< " + selector.hashCode() + " > 多路复用器上发生的事件是 ：可写事件");
                    } else if (selectedKey.isAcceptable()) {
                        System.out.println("线程 ：" + Thread.currentThread().getName() + ",当前类 ；" + getClass().getName() + " 的 hashCode :" + this.hashCode() + ",此 selector< " + selector.hashCode() + " > 多路复用器上发生的事件是 ：接收请求事件");
                    } else if (selectedKey.isConnectable()) {
                        System.out.println("线程 ：" + Thread.currentThread().getName() + ",当前类 ；" + getClass().getName() + " 的 hashCode :" + this.hashCode() + ",此 selector< " + selector.hashCode() + " > 多路复用器上发生的事件是 ：请求连接事件");
                    } else {
                        System.out.println("线程 ：" + Thread.currentThread().getName() + ",当前类 ；" + getClass().getName() + " 的 hashCode :" + this.hashCode() + ",此 selector< " + selector.hashCode() + " > 多路复用器上发生的事件是 ：其他事件");
                    }
                    dispatch(selectedKey); // 根據事件的key進行調度
                }
                selectedKeys.clear();
            } catch (IOException e) {
                e.getLocalizedMessage();
            }
        }
    }

    /*
     * name: dispatch(SelectionKey key)
     * description: 調度方法，根據事件綁定的對象開新線程
     */
    private void dispatch(SelectionKey key) {
        //获取之前绑定的对象
        Handler r = (Handler) (key.attachment()); // 根據事件之key綁定的對象開新線程
        if (r != null)
            r.processes();
    }

}
